﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio;
using TFDP.VsPackage.Support.TargetProjects;
using TFDP.Common;
using TFDP.VisualStudioInterop;

namespace TFDP.VsPackage.Support
{
    public static class VsExtensions
    {
        public static FileEditRequestResult CanEdit(this IVsQueryEditQuerySave2 queryEditService, string path)
        {
            uint verdict = 0;
            uint moreInfo = 0;
            FileEditRequestResult requestResult = null;

            int result = queryEditService.QueryEditFiles(
                (uint)(tagVSQueryEditFlags.QEF_SilentMode | tagVSQueryEditFlags.QEF_ImplicitEdit),
                1,
                new string[] { path },
                null,
                null,
                out verdict,
                out moreInfo
            );

            if (result != VSConstants.S_OK)
            {
                requestResult = new FileEditRequestResult(
                    false,
                    String.Format(
                        "Edit access denied: {0} {1}",
                        VsInteropUtilities.QueryEditResultToString((tagVSQueryEditResult)verdict),
                        VsInteropUtilities.QueryEditResultFlagsToString((tagVSQueryEditResultFlags)moreInfo)
                    )
                );
            }
            else
            {
                requestResult = new FileEditRequestResult(
                    true,
                    VsInteropUtilities.QueryEditResultFlagsToString((tagVSQueryEditResultFlags)moreInfo)
                );
            }

            return requestResult;
        }

        internal static ITargetProject GetTargetProject(this GeneratedArtifact artifact)
        {
            IVsHierarchy hierarchy = (IVsHierarchy)FindProject(artifact.ProjectName);

            if (hierarchy == null)
            {
                throw new Exception(String.Format("Project {0} was not found in solution", artifact.ProjectName));
            }

            ITargetProject project = null;

            if (VsInteropUtilities.IsSqlDatabaseProject(hierarchy))
            {
                project = new DatabaseProject();
                project.Initialize(hierarchy);
            }
            else if (VsInteropUtilities.IsVsLangProject(hierarchy))
            {
                project = new VsLangProject();
                project.Initialize(hierarchy);
            }
            else if (VsInteropUtilities.IsModelingProject(hierarchy))
            {
                project = new ModelingProject();
                project.Initialize(hierarchy);
            }
            else
            {
                project = new VsProjectProject();
                project.Initialize(hierarchy);
            }

            return project;
        }

        private static IVsProject FindProject(string projectName)
        {
            IVsSolution solutionService = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(IVsSolution)) as IVsSolution;

            if (solutionService != null)
            {
                List<IVsProject> projects = VsInteropUtilities.ProjectsInSolution(solutionService).ToList();
                //IEnumHierarchies enumerator = null;
                //Guid guid = Guid.Empty;
                //List<IVsProject> projects = new List<IVsProject>();

                //solutionService.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref guid, out enumerator);
                //IVsHierarchy[] hierarchy = new IVsHierarchy[1] { null };
                //uint fetched = 0;
                //for (enumerator.Reset(); enumerator.Next(1, hierarchy, out fetched) == VSConstants.S_OK && fetched == 1; /*nothing*/)
                //{
                //    projects.Add((IVsProject)hierarchy[0]);
                //}

                var matches = projects.Where(pi => VsInteropUtilities.GetEnvDTEProject((IVsHierarchy)pi).Name == projectName).Select(pi => pi);

                if (matches.Count() == 1)
                    return matches.First();
                else
                    return null;
            }
            else
                return null;
        }
    }
}
